package com.zzj.controller;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.zzj.base.Result;
import com.zzj.base.ResultCode;
import com.zzj.entity.User;
import com.zzj.model.dto.LoginDTO;
import com.zzj.model.dto.admin.AdminRegisterDTO;
import com.zzj.service.IUserService;
import com.zzj.service.RedisService;
import com.zzj.utils.IPUtil;
import com.zzj.utils.JWTUtil;
import com.zzj.utils.RedisUtil;
import io.netty.util.internal.StringUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.log4j.Log4j2;
import org.apache.http.HttpHeaders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

@Log4j2
@RestController
public class
LoginController {

    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedisService redisService;
    @Resource
    private IUserService userService;
    @Resource
    private IPUtil ipUtil;


    /**
     * 登录认证
     *
     * @param in 登录 数据传输对象
     */
    @Transactional
    @PostMapping("/login")
    public Result login(HttpServletRequest request, @RequestBody @Validated LoginDTO in) throws Exception {
        String ip =ipUtil.getIP(request);
        String address = ipUtil.getProvinceByIP(ip);
        log.info("ip:{},address:{}", ip, address);

        User user = userService.findUserByUsername(in.getUsername(), in.getPassword());
        if (user == null) {
            return Result.error("用户名或密码错误");
        }
        if (user.getStatus() > 10 && user.getStatus() < 100) {
            return Result.error("账号正在审核中");
        }
        user = userService.updateIpAddress(user.getId(), ip, address);


        String token = JWTUtil.generateToken(in.getUsername());
        String refreshToken = UUID.randomUUID().toString();
        redisService.setRefreshToken(token, refreshToken, user.getUsername());

        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("token", token);
        hashMap.put("refreshToken", refreshToken);
        hashMap.put("userInfo", JSON.toJSONString(user));
        return Result.success(hashMap);
    }

    /**
     * 注销 token加入黑名单
     *
     * @param token
     * @return
     */
    @PostMapping("/logout")
    public Result logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION) String token) {
        boolean verify = JWTUtil.verify(token);
        if (!verify) {
            return new Result(ResultCode.TOKEN_EXPIRED);
        }
        addBlackList(token);
        return Result.success("注销成功");
    }

    /**
     * 重新获取token
     *
     * @param refreshToken
     * @return
     */
    @Transactional
    @PostMapping("/refreshToken")
    public Result refreshToken(@RequestParam String refreshToken) {
        String username = redisService.getUsername(refreshToken);
        if (StringUtil.isNullOrEmpty(username)) {
            return new Result<>(ResultCode.REFRESH_TOKEN_EXPIRED);
        }
        userService.updateLoginTime(username);
        String token = redisService.getToken(refreshToken);
        addBlackList(token);

        String newToken = JWTUtil.generateToken(username);
        String newRefreshToken = UUID.randomUUID().toString();
        redisService.removeRefreshToken(refreshToken);
        redisService.setRefreshToken(newToken, newRefreshToken, username);

        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("token", newToken);
        hashMap.put("refreshToken", newRefreshToken);
        return Result.success(hashMap);
    }


    /**
     * 管理员注册
     *
     * @return
     */
    @PostMapping("/adminRegister")
    public Result register(@RequestBody @Validated AdminRegisterDTO in) throws Exception {
        User user = userService.findUserByUsername(in.getUsername());
        if (user == null) {
            userService.createUser(in.getUsername(), in.getPassword(), 55);
            return Result.success("注册成功，等待管理员审核");
        } else {
            return Result.error("注册失败，用户名已存在");
        }
    }


    /**
     * token加入黑名单
     *
     * @param token
     */
    private void addBlackList(String token) {
        DecodedJWT decode = JWT.decode(token);
        Date expiresAt = decode.getExpiresAt();
        Date now = new Date();
        long l = expiresAt.getTime() - now.getTime();
        if (l > 0) {
            redisUtil.hset(JWTUtil.BLACK_KEY, token, 1, l / 1000);
        }
    }
}
